今天要來玩玩新的 library Glance,因為還在 alpha 階段,所以建議大家先體驗看看就好,以下如有解釋不清或是描述錯誤的地方還請大家多多指教:
Glance 這套 library 主要是強調以更快更簡單的方式來建立 app widget,他是以 jetpack compose 為基底的介面操作,所以在開發的時候要設置 compose,轉譯成 RemoteView 最終呈現在畫面上,以下列了幾個 Android 12 以後才出現的設置:
appwidget-provider : targetCellWidth/targetCellHeight (設置 default 格數占比)minHeight/minWidth (dp)appwidget-provider : MaxResizeWidth/MaxResizeHeight, MinResizeWidth/MinResizeHeight (限制可 resize 的最大及最小範圍 - dp)appwidget-provider : description (什麼功能的 widget 敘述)appwidget-provider : previewLayout (在選擇器上呈現的 preview)previewImage 來設置靜態的圖示,previewLayout 可以精準的呈現資料設置 dependency 及 enable Compose
dependencies {
    // For AppWidgets support
    implementation "androidx.glance:glance-appwidget:1.0.0-alpha05"
}
android {
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.2.0-beta01" 
    }
    kotlinOptions {
        jvmTarget = "1.8" // 這裡我使用 11
    }
}
這邊要注意的地方是,compose 有對應的 kotlin 版本,針對自己所運行的版本去設置 compose 版號,請參考這份
建立 widget 設定要呈現的 style
class WeatherWidget : GlanceAppWidget() {
    @Composable
    override fun Content() {
        Column(modifier = GlanceModifier.padding(all = 16.dp)) {
            val prefs = currentState<Preferences>()
            val checkWarn = prefs[booleanPreferencesKey("uva_warn")] ?: false
            Row(modifier = GlanceModifier.padding(16.dp)) {
                Text(text = "UVA")
                Switch(checked = checkWarn, onCheckedChange = actionRunCallback<SwitchAction>())
            }
        }
    }
}
設置 switch 的 action 行為
class SwitchAction : ActionCallback {
    override suspend fun onAction(
        context: Context,
        glanceId: GlanceId,
        parameters: ActionParameters
    ) {
        updateAppWidgetState(context, PreferencesGlanceStateDefinition, glanceId) {
            it.toMutablePreferences()
                .apply {
                    val checkWarn = this[booleanPreferencesKey("uva_warn")] ?: false
                    this[booleanPreferencesKey("uva_warn")] = !checkWarn
                }
        }
        WeatherWidget().update(context, glanceId)
    }
}
設置 AppWidgetProvider,在 Glance 中叫做 GlanceAppWidgetReceiver(),他繼承了原本的 AppWidgetProvider:
class WeatherWidgetProvider: GlanceAppWidgetReceiver() {
    override val glanceAppWidget: GlanceAppWidget = WeatherWidget()
}
在 resourece 建立 appwidget-provider
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
        android:minWidth="250dp"
        android:minHeight="40dp"
        android:resizeMode="horizontal|vertical"
        android:updatePeriodMillis="86400000"
        android:widgetCategory="home_screen">
</appwidget-provider>
GlanceAppWidgetReceiver 是一個 BroadcastReceiver,所以要在 Manifest 註冊 (與舊有的方式依樣)
<receiver
        android:name=".widget.WeatherWidgetProvider"
        android:exported="true"
        android:label="天氣預告">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
         android:name="android.appwidget.provider"
         android:resource="@xml/weather_widget_info" />
</receiver>
運行之後就可以看見帶有 switch 的 widget 了